home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsrmt / fsrmtAttributes.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  35KB  |  1,018 lines

  1. /*
  2.  * fsAttributes.c --
  3.  *
  4.  *    This has procedures for operations done on remote file attributes.
  5.  *    The general strategy when getting attributes is to make one call to
  6.  *    the name server to get an initial version of the attributes, and
  7.  *    then make another call to the I/O server to update things like
  8.  *    the access time and modify time.  There are two ways to get to
  9.  *    the name server, either via a pathname or an open file.  The
  10.  *    I/O server is always contacted using a fileID.
  11.  *    The 3 corrsponding RPCs are:
  12.  *    RPC_FS_GET_ATTR_PATH    To get attributes from name server given path.
  13.  *    RPC_FS_GET_ATTR        To get attributes from name server given fileID
  14.  *    RPC_FS_GET_IO_ATTR    To get (a few) attributes from the I/O server.
  15.  *    Setting attributes is done the same way, and there are three more
  16.  *    corresponding RPCs.
  17.  *
  18.  * Copyright 1987 Regents of the University of California
  19.  * All rights reserved.
  20.  * Permission to use, copy, modify, and distribute this
  21.  * software and its documentation for any purpose and without
  22.  * fee is hereby granted, provided that the above copyright
  23.  * notice appear in all copies.  The University of California
  24.  * makes no representations about the suitability of this
  25.  * software for any purpose.  It is provided "as is" without
  26.  * express or implied warranty.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsrmt/fsrmtAttributes.c,v 9.9 91/09/10 18:23:47 rab Exp $ SPRITE (Berkeley)";
  31. #endif not lint
  32.  
  33.  
  34. #include <sprite.h>
  35. #include <fs.h>
  36. #include <fsutil.h>
  37. #include <fslcl.h>
  38. #include <fsNameOps.h>
  39. #include <fsconsist.h>
  40. #include <fscache.h>
  41. #include <fsdm.h>
  42. #include <fsStat.h>
  43. #include <recov.h>
  44. #include <rpc.h>
  45.  
  46. #include <string.h>
  47. #include <stdio.h>
  48.  
  49. static Fs_HandleHeader *VerifyIOHandle _ARGS_((Fs_FileID *fileIDPtr));
  50.  
  51.  
  52. /*
  53.  * Return parameters from RPC_FS_GET_ATTR_PATH.  The file ID is used to
  54.  * get to the I/O server.
  55.  */
  56. typedef struct FsRemoteGetAttrResults {
  57.     Fs_Attributes    attributes;
  58.     Fs_FileID        fileID;
  59. } FsRemoteGetAttrResults;
  60.  
  61.  
  62. /*
  63.  *----------------------------------------------------------------------
  64.  *
  65.  * FsrmtGetAttrPath --
  66.  *
  67.  *    Get the attributes of a remote Sprite file given its name.  This
  68.  *    is called from Fs_GetAttributes for files named by remote servers.
  69.  *    Note:  the attributes from the disk descriptor on the name server
  70.  *    are returned.  The attributes need to be updated by the I/O server
  71.  *    if there is one.
  72.  *
  73.  * Results:
  74.  *    A return code from the RPC or the remote server.
  75.  *
  76.  * Side effects:
  77.  *    FS_RPC_GET_ATTR.
  78.  *
  79.  *----------------------------------------------------------------------
  80.  */
  81. ReturnStatus
  82. FsrmtGetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  83.                  newNameInfoPtrPtr)
  84.     Fs_HandleHeader *prefixHandle;    /* Handle from the prefix table */
  85.     char           *relativeName;    /* The name of the file. */
  86.     Address        argsPtr;        /* Bundled arguments for us */
  87.     Address        resultsPtr;        /* Where to store attributes */
  88.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  89.                      * its domain during the lookup. */
  90. {
  91.     ReturnStatus         status;
  92.     Fs_OpenArgs            *openArgsPtr;
  93.     Fs_GetAttrResults        *getAttrResultsPtr;
  94.     Fs_GetAttrResultsParam    getAttrResultsParam;
  95.     Rpc_Storage            storage;
  96.     char            replyName[FS_MAX_PATH_NAME_LENGTH];     /* This
  97.                              * may get filled with a
  98.                              * redirected pathname. */
  99.  
  100.     openArgsPtr = (Fs_OpenArgs *) argsPtr;
  101.     getAttrResultsPtr = (Fs_GetAttrResults *)resultsPtr;
  102.  
  103.     storage.requestParamPtr = (Address) openArgsPtr;
  104.     storage.requestParamSize = sizeof(Fs_OpenArgs);
  105.     storage.requestDataPtr = (Address) relativeName;
  106.     storage.requestDataSize = strlen(relativeName) + 1;
  107.     storage.replyParamPtr = (Address) &(getAttrResultsParam);
  108.     storage.replyParamSize = sizeof(Fs_GetAttrResultsParam);
  109.     storage.replyDataPtr = (Address) replyName;
  110.     storage.replyDataSize = FS_MAX_PATH_NAME_LENGTH;
  111.  
  112.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_GET_ATTR_PATH,
  113.             &storage);
  114.      if (status == SUCCESS) {
  115.     /*
  116.      * The return param area has a fileID that we need.  The
  117.      * return parameter area has also been filled in with
  118.      * the attributes.
  119.      */
  120.     *(getAttrResultsPtr->fileIDPtr) =
  121.          getAttrResultsParam.attrResults.fileID;
  122.     *(getAttrResultsPtr->attrPtr) =
  123.         getAttrResultsParam.attrResults.attrs;
  124.     } else if (status == FS_LOOKUP_REDIRECT) {
  125.     /*
  126.      * Copy the info from our stack to a buffer for our caller
  127.      */
  128.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  129.     (*newNameInfoPtrPtr)->prefixLength = getAttrResultsParam.prefixLength;
  130.     (void)strcpy((*newNameInfoPtrPtr)->fileName, replyName);
  131.     return(FS_LOOKUP_REDIRECT);
  132.     }
  133.  
  134.     return(status);
  135. }
  136.  
  137. /*
  138.  *----------------------------------------------------------------------
  139.  *
  140.  * Fsrmt_RpcGetAttrPath --
  141.  *
  142.  *    Service stub for the RPC_FS_GET_ATTR_PATH call.  This is used to
  143.  *    get the attributes from the disk descriptor of a file.  NOTE:  the
  144.  *    attributes are not complete until the I/O server for the (non-regular)
  145.  *    file is contacted.  This routine does, however, suck in attributes
  146.  *    of regular files that are cached.
  147.  *
  148.  * Results:
  149.  *    If this procedure returns SUCCESS then a reply has been sent to
  150.  *    the client.  If the arguments are bad then an error is 
  151.  *    returned and the main level sends back an error reply.
  152.  *
  153.  * Side effects:
  154.  *    Allocates a buffer to return the results in.
  155.  *    
  156.  *
  157.  *----------------------------------------------------------------------
  158.  */
  159. /*ARGSUSED*/
  160. ReturnStatus
  161. Fsrmt_RpcGetAttrPath(srvToken, clientID, command, storagePtr)
  162.     ClientData          srvToken;    /* Handle on server process passed to
  163.                       * Rpc_Reply */
  164.     int          clientID;    /* Sprite ID of client host */
  165.     int          command;    /* IGNORED */
  166.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  167.                      * request buffers and also indicate 
  168.                      * the exact amount of data in the 
  169.                      * request buffers.  The reply fields 
  170.                      * are initialized to NIL for the
  171.                       * pointers and 0 for the lengths.  
  172.                      * This can be passed to Rpc_Reply */
  173. {
  174.     register Fs_OpenArgs        *openArgsPtr;    /* Tmp pointer into openParams*/
  175.     Fs_GetAttrResults         getAttrResults;    /* Results from local  routine */
  176.     Fs_GetAttrResultsParam    *getAttrResultsParamPtr;    /* rpc param
  177.                                  * bundle */
  178.     Fs_HandleHeader        *prefixHandle;    /* Handle for domain */
  179.     ReturnStatus        status;        /* General return code */
  180.     Fs_RedirectInfo        *newNameInfoPtr;/* For prefix re-directs,
  181.                          * unallocated since proc call
  182.                          * allocates space for it. */
  183.     int                domainType;
  184.  
  185.     openArgsPtr = (Fs_OpenArgs *) storagePtr->requestParamPtr;
  186.  
  187.     if (openArgsPtr->prefixID.serverID != rpc_SpriteID) {
  188.     /*
  189.      * Filesystem mis-match.
  190.      */
  191.     return(GEN_INVALID_ARG);
  192.     }
  193.     prefixHandle = (*fsio_StreamOpTable[openArgsPtr->prefixID.type].clientVerify)
  194.         (&openArgsPtr->prefixID, clientID, &domainType);
  195.     if (prefixHandle == (Fs_HandleHeader *)NIL) {
  196.     return(FS_STALE_HANDLE);
  197.     }
  198.     Fsutil_HandleRelease(prefixHandle, TRUE);
  199.  
  200.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  201.     getAttrResultsParamPtr = mnew(Fs_GetAttrResultsParam);
  202.  
  203.     getAttrResults.attrPtr = &(getAttrResultsParamPtr->attrResults.attrs);
  204.     getAttrResults.fileIDPtr = &(getAttrResultsParamPtr->attrResults.fileID);
  205.  
  206.     fs_Stats.srvName.getAttrs++;
  207.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_GET_ATTR])(prefixHandle,
  208.         (char *) storagePtr->requestDataPtr, (Address)openArgsPtr,
  209.         (Address)(&getAttrResults), &newNameInfoPtr);
  210.  
  211.     if (status == SUCCESS) {
  212.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  213.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  214.     storagePtr->replyDataPtr = (Address) NIL;
  215.     storagePtr->replyDataSize = 0;
  216.     } else if (status == FS_LOOKUP_REDIRECT) {
  217.     /*
  218.      * The file is not found on this server, but somewhere else.
  219.      */
  220.     getAttrResultsParamPtr->prefixLength = newNameInfoPtr->prefixLength;
  221.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  222.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  223.     storagePtr->replyDataSize = strlen(newNameInfoPtr->fileName) + 1;
  224.     storagePtr->replyDataPtr =
  225.         (Address) malloc(storagePtr->replyDataSize);
  226.     (void)strcpy((char *) storagePtr->replyDataPtr, newNameInfoPtr->fileName);
  227.     free((Address)newNameInfoPtr);
  228.     }
  229.     if (status == SUCCESS || status == FS_LOOKUP_REDIRECT) {
  230.     Rpc_ReplyMem    *replyMemPtr;
  231.  
  232.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  233.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  234.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  235.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  236.             (ClientData)replyMemPtr);
  237.         return(SUCCESS);
  238.     } else {
  239.     free((Address) getAttrResultsParamPtr);
  240.         return(status);
  241.     }
  242. }
  243.  
  244.  
  245. /*
  246.  *----------------------------------------------------------------------
  247.  *
  248.  * FsrmtSetAttrPath --
  249.  *
  250.  *    Set the attributes of a remote Sprite file given its path name.
  251.  *    This is called from Fs_SetAttributes.  This used the
  252.  *    RPC_FS_SET_ATTR_PATH rpc to invoke FslclSetAttrPath on the
  253.  *    name server.
  254.  *
  255.  * Results:
  256.  *    None.
  257.  *
  258.  * Side effects:
  259.  *    None.
  260.  *
  261.  *----------------------------------------------------------------------
  262.  */
  263.  
  264. ReturnStatus
  265. FsrmtSetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  266.                  newNameInfoPtrPtr)
  267.     Fs_HandleHeader *prefixHandle;   /* Token from the prefix table */
  268.     char           *relativeName;   /* The name of the file. */
  269.     Address        argsPtr;        /* Bundled arguments for us */
  270.     Address        resultsPtr;        /* FileID */
  271.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  272.                      * its domain during the lookup. */
  273. {
  274.     ReturnStatus         status;
  275.     Rpc_Storage            storage;
  276.     char            replyName[FS_MAX_PATH_NAME_LENGTH];
  277.     Fs_GetAttrResultsParam    getAttrResultsParam;
  278.     Fs_FileID            *fileIDPtr;
  279.  
  280.     storage.requestParamPtr = (Address) argsPtr;
  281.     storage.requestParamSize = sizeof(Fs_SetAttrArgs);
  282.     storage.requestDataPtr = (Address) relativeName;
  283.     storage.requestDataSize = strlen(relativeName) + 1;
  284.     storage.replyParamPtr = (Address) &(getAttrResultsParam);
  285.     storage.replyParamSize = sizeof(Fs_GetAttrResultsParam);
  286.     storage.replyDataPtr = (Address) replyName;
  287.     storage.replyDataSize = FS_MAX_PATH_NAME_LENGTH;
  288.  
  289.     fileIDPtr = (Fs_FileID *) resultsPtr;
  290.  
  291.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_SET_ATTR_PATH,
  292.             &storage);
  293.     if (status == SUCCESS) {
  294.     /*
  295.      * Copy result fileID to resultsPtr (== fileIDPtr).
  296.      */
  297.     (* fileIDPtr) = getAttrResultsParam.attrResults.fileID;
  298.     } else if (status == FS_LOOKUP_REDIRECT) {
  299.     /*
  300.      * Copy the info from our stack to a buffer for our caller.
  301.      */
  302.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  303.     (*newNameInfoPtrPtr)->prefixLength = getAttrResultsParam.prefixLength;
  304.     (void)strcpy((*newNameInfoPtrPtr)->fileName, replyName);
  305.     }
  306.  
  307.     return(status);
  308. }
  309.  
  310. /*
  311.  *----------------------------------------------------------------------
  312.  *
  313.  * Fsrmt_RpcSetAttrPath --
  314.  *
  315.  *    Service stub for the RPC_FS_SET_ATTR_PATH call.  This branches
  316.  *    to FslclSetAttrPath which sets the attributes on the file descriptor.
  317.  *
  318.  * Results:
  319.  *    If this procedure returns SUCCESS then a reply has been sent to
  320.  *    the client.  If the arguments are bad then an error is 
  321.  *    returned and the main level sends back an error reply.
  322.  *
  323.  * Side effects:
  324.  *    Allocates a buffer to return the results in.
  325.  *    
  326.  *
  327.  *----------------------------------------------------------------------
  328.  */
  329. /*ARGSUSED*/
  330. ReturnStatus
  331. Fsrmt_RpcSetAttrPath(srvToken, clientID, command, storagePtr)
  332.     ClientData          srvToken;    /* Handle on server process passed to
  333.                       * Rpc_Reply */
  334.     int          clientID;    /* Sprite ID of client host */
  335.     int          command;    /* IGNORED */
  336.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  337.                      * request buffers and also indicate 
  338.                      * the exact amount of data in the 
  339.                      * request buffers.  The reply fields 
  340.                      * are initialized to NIL for the
  341.                       * pointers and 0 for the lengths.  
  342.                      * This can be passed to Rpc_Reply */
  343. {
  344.     Fs_FileID            *ioFileIDPtr;    /* Results from local routine */
  345.     Fs_HandleHeader        *prefixHandle;    /* Handle for domain */
  346.     ReturnStatus        status;        /* General return code */
  347.     Fs_SetAttrArgs        *setAttrArgsPtr;
  348.     Fs_RedirectInfo        *newNameInfoPtr;/* For prefix re-directs */
  349.     Fs_GetAttrResultsParam    *getAttrResultsParamPtr;    /* rpc param
  350.                                  * bundle */
  351.     int                domainType;
  352.  
  353.     setAttrArgsPtr = (Fs_SetAttrArgs *) storagePtr->requestParamPtr;
  354.  
  355.     prefixHandle =
  356.     (*fsio_StreamOpTable[setAttrArgsPtr->openArgs.prefixID.type].clientVerify)
  357.         (&setAttrArgsPtr->openArgs.prefixID, clientID, &domainType);
  358.     if (prefixHandle == (Fs_HandleHeader *)NIL) {
  359.     return(FS_STALE_HANDLE);
  360.     }
  361.     Fsutil_HandleRelease(prefixHandle, TRUE);
  362.  
  363.  
  364.     fs_Stats.srvName.setAttrs++;
  365.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  366.     getAttrResultsParamPtr = mnew(Fs_GetAttrResultsParam);
  367.     ioFileIDPtr = &(getAttrResultsParamPtr->attrResults.fileID);
  368.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_SET_ATTR])(prefixHandle,
  369.         (char *) storagePtr->requestDataPtr,
  370.         (Address) storagePtr->requestParamPtr,
  371.         (Address) ioFileIDPtr, &newNameInfoPtr);
  372.  
  373.     if (status == SUCCESS) {
  374.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  375.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  376.     storagePtr->replyDataPtr = (Address) NIL;
  377.     storagePtr->replyDataSize = 0;
  378.     } else if (status == FS_LOOKUP_REDIRECT) {
  379.     /*
  380.      * The file is not found on this server.
  381.      */
  382.     getAttrResultsParamPtr->prefixLength = newNameInfoPtr->prefixLength;
  383.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  384.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  385.     storagePtr->replyDataSize = strlen(newNameInfoPtr->fileName) + 1;
  386.     storagePtr->replyDataPtr =
  387.         (Address) malloc(storagePtr->replyDataSize);
  388.     (void)strcpy((char *) storagePtr->replyDataPtr, newNameInfoPtr->fileName);
  389.     free((Address)newNameInfoPtr);
  390.     }
  391.     if (status == SUCCESS || status == FS_LOOKUP_REDIRECT) {
  392.     Rpc_ReplyMem    *replyMemPtr;
  393.  
  394.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  395.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  396.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  397.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  398.         (ClientData)replyMemPtr);
  399.         return(SUCCESS);
  400.     } else {
  401.     free((Address)getAttrResultsParamPtr);
  402.         return(status);
  403.     }
  404. }
  405.  
  406. /*
  407.  *----------------------------------------------------------------------
  408.  *
  409.  * FsrmtGetAttr --
  410.  *
  411.  *    Get the attributes of a remote file given its fileID.  This is called
  412.  *    from Fs_GetAttrStream.  This does an RPC to the name server which
  413.  *    then calls FslclGetAttr.
  414.  *
  415.  * Results:
  416.  *    An error code.
  417.  *
  418.  * Side effects:
  419.  *    Fills in the attributes structure with info from the file server.
  420.  *
  421.  *----------------------------------------------------------------------
  422.  */
  423. /*ARGSUSED*/
  424. ReturnStatus
  425. FsrmtGetAttr(fileIDPtr, clientID, attrPtr)
  426.     register Fs_FileID        *fileIDPtr;    /* Identfies file */
  427.     int                clientID;    /* IGNORED, implicitly passed
  428.                          * by the RPC system. */
  429.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  430. {
  431.     register ReturnStatus    status;
  432.     Rpc_Storage storage;
  433.  
  434.     storage.requestParamPtr = (Address) fileIDPtr;
  435.     storage.requestParamSize = sizeof(Fs_FileID);
  436.     storage.requestDataPtr = (Address) NIL;
  437.     storage.requestDataSize = 0;
  438.     storage.replyParamPtr = (Address) attrPtr;
  439.     storage.replyParamSize = sizeof(Fs_Attributes);
  440.     storage.replyDataPtr = (Address) NIL;
  441.     storage.replyDataSize = 0;
  442.  
  443.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_GET_ATTR, &storage);
  444.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  445.     status == RPC_SERVICE_DISABLED) {
  446.     /*
  447.      * If there was a problem at the server then try to recover
  448.      * the handle.  We may not have a handle in the case of devices.
  449.      * In that case the fileID we have here comes from the stream's
  450.      * nameInfo, which doesn't get installed into the handle table.
  451.      */
  452.     register Fs_HandleHeader *hdrPtr = Fsutil_HandleFetch(fileIDPtr);
  453.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  454.         Fsutil_WantRecovery(hdrPtr);
  455.         Fsutil_HandleRelease(hdrPtr, TRUE);
  456.     }
  457.     }
  458.     return(status);
  459. }
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * Fsrmt_RpcGetAttr --
  465.  *
  466.  *    Service stub for the RPC_FS_GET_ATTR call.  This calls FslclGetAttr
  467.  *    (or FspdevPseudoGetAttr) to get the attributes of a file.  This
  468.  *    is a name server operation used when the file is already open.
  469.  *    Note: Attributes are not complete until the I/O server has also
  470.  *    been contacted.  See Fsrmt_RpcGetIOAttr.
  471.  *
  472.  * Results:
  473.  *    If this procedure returns SUCCESS then a reply has been sent to
  474.  *    the client.  If the arguments are bad then an error is 
  475.  *    returned and the main level sends back an error reply.
  476.  *
  477.  * Side effects:
  478.  *    Allocates a buffer to return the results in.
  479.  *
  480.  *----------------------------------------------------------------------
  481.  */
  482. /*ARGSUSED*/
  483. ReturnStatus
  484. Fsrmt_RpcGetAttr(srvToken, clientID, command, storagePtr)
  485.     ClientData          srvToken;    /* Handle on server process passed to
  486.                       * Rpc_Reply */
  487.     int          clientID;    /* Sprite ID of client host */
  488.     int          command;    /* IGNORED */
  489.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  490.                      * request buffers and also indicate 
  491.                      * the exact amount of data in the 
  492.                      * request buffers.  The reply fields 
  493.                      * are initialized to NIL for the
  494.                      * pointers and 0 for the lengths.  
  495.                      * This can be passed to Rpc_Reply */
  496. {
  497.     register ReturnStatus    status;
  498.     Fs_HandleHeader        *tHdrPtr;
  499.     register Fs_HandleHeader    *hdrPtr;
  500.     register Fs_FileID        *fileIDPtr;
  501.     register Fs_Attributes    *attrPtr;
  502.     Rpc_ReplyMem        *replyMemPtr;
  503.     int                domainType = FS_LOCAL_DOMAIN;
  504.  
  505.     fileIDPtr = (Fs_FileID *) storagePtr->requestParamPtr;
  506.     hdrPtr = VerifyIOHandle(fileIDPtr);
  507.     if (fileIDPtr->type == FSIO_LCL_PFS_STREAM) {
  508.     if (hdrPtr == (Fs_HandleHeader *)NIL) {
  509.         return(FS_STALE_HANDLE);
  510.     }
  511.     domainType = FS_PSEUDO_DOMAIN;
  512.     } else if (hdrPtr == (Fs_HandleHeader *)NIL) {
  513.     status = Fsio_LocalFileHandleInit(fileIDPtr, (char *)NIL,
  514.             (Fsdm_FileDescriptor *) NIL, FALSE, 
  515.             (Fsio_FileIOHandle **)&tHdrPtr);
  516.     if (status != SUCCESS) {
  517.         return(status);
  518.     }
  519.     hdrPtr = tHdrPtr;
  520.     }
  521.     Fsutil_HandleUnlock(hdrPtr);
  522.  
  523.     fs_Stats.srvName.getAttrs++;
  524.     attrPtr = mnew(Fs_Attributes);
  525.     status = (*fs_AttrOpTable[domainType].getAttr)(fileIDPtr, clientID, attrPtr);
  526. #ifdef lint
  527.     status = FslclGetAttr(fileIDPtr, clientID, attrPtr);
  528.     status = FspdevPseudoGetAttr(fileIDPtr, clientID, attrPtr);
  529. #endif lint
  530.     Fsutil_HandleRelease(hdrPtr, FALSE);
  531.  
  532.     storagePtr->replyParamPtr = (Address) attrPtr;
  533.     storagePtr->replyParamSize = sizeof(Fs_Attributes);
  534.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  535.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  536.     replyMemPtr->dataPtr = (Address) NIL;
  537.  
  538.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  539.         (ClientData)replyMemPtr);
  540.     return(SUCCESS);
  541. }
  542.  
  543. /*
  544.  * Parameters for RPC_FS_SET_ATTR.  This is a sub-set of Fs_SetAttrArgs
  545.  * (which has extra stuff required to handle path name lookup).
  546.  */
  547.  
  548. typedef struct FsRemoteSetAttrParams {
  549.     Fs_FileID        fileID;
  550.     Fs_UserIDs        ids;
  551.     Fs_Attributes    attrs;
  552.     int            flags;
  553. } FsRemoteSetAttrParams;
  554.  
  555. /*
  556.  *----------------------------------------------------------------------
  557.  *
  558.  * FsrmtSetAttr
  559.  *
  560.  *    Set selected attributes of a remote file given its fileID.  This
  561.  *    is called from Fs_SetAttrStream.  This does the RPC_FS_SET_ATTR
  562.  *    remote call which invokes FslclSetAttr on the name server.
  563.  *
  564.  * Results:
  565.  *    None.
  566.  *
  567.  * Side effects:
  568.  *    None.
  569.  *
  570.  *----------------------------------------------------------------------
  571.  */
  572.  
  573. ReturnStatus
  574. FsrmtSetAttr(fileIDPtr, attrPtr, idPtr, flags)
  575.     Fs_FileID        *fileIDPtr;
  576.     Fs_Attributes    *attrPtr;
  577.     Fs_UserIDs         *idPtr;
  578.     int            flags;
  579. {
  580.     ReturnStatus status;
  581.     Rpc_Storage storage;
  582.     FsRemoteSetAttrParams params;
  583.  
  584.     params.fileID = *fileIDPtr;
  585.     params.ids = *idPtr;
  586.     params.attrs = *attrPtr;
  587.     params.flags = flags;
  588.     storage.requestParamPtr = (Address)¶ms;
  589.     storage.requestParamSize = sizeof(FsRemoteSetAttrParams);
  590.     storage.requestDataPtr = (Address)NIL;;
  591.     storage.requestDataSize = 0;
  592.     storage.replyParamPtr = (Address)NIL;
  593.     storage.replyParamSize = 0;
  594.     storage.replyDataPtr = (Address)NIL;
  595.     storage.replyDataSize = 0;
  596.  
  597.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_SET_ATTR, &storage);
  598.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  599.     status == RPC_SERVICE_DISABLED) {
  600.     register Fs_HandleHeader *hdrPtr = Fsutil_HandleFetch(fileIDPtr);
  601.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  602.         Fsutil_WantRecovery(hdrPtr);
  603.         Fsutil_HandleRelease(hdrPtr, TRUE);
  604.     }
  605.     }
  606.  
  607.     return(status);
  608. }
  609.  
  610. /*
  611.  *----------------------------------------------------------------------
  612.  *
  613.  * Fsrmt_RpcSetAttr --
  614.  *
  615.  *    Service stub for RPC_FS_SET_ATTR.  This calls FslclSetAttr.
  616.  *
  617.  * Results:
  618.  *    If this procedure returns SUCCESS then a reply has been sent to
  619.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  620.  *    returned and the main level sends back an error reply.
  621.  *
  622.  * Side effects:
  623.  *    Uses FslclSetAttr to set attributes in the file descriptor.
  624.  *
  625.  *----------------------------------------------------------------------
  626.  */
  627. /*ARGSUSED*/
  628. ReturnStatus
  629. Fsrmt_RpcSetAttr(srvToken, clientID, command, storagePtr)
  630.     ClientData          srvToken;    /* Handle on server process passed to
  631.                       * Rpc_Reply */
  632.     int          clientID;    /* Sprite ID of client host */
  633.     int          command;    /* IGNORED */
  634.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  635.                      * request buffers and also indicate 
  636.                      * the exact amount of data in the 
  637.                      * request buffers.  The reply fields 
  638.                      * are initialized to NIL for the
  639.                       * pointers and 0 for the lengths.  
  640.                      * This can be passed to Rpc_Reply */
  641. {
  642.     Fs_HandleHeader        *hdrPtr;
  643.     register Fs_FileID        *fileIDPtr;
  644.     register Fs_Attributes    *attrPtr;
  645.     register ReturnStatus    status;
  646.     FsRemoteSetAttrParams    *paramPtr;
  647.     int                domainType = FS_LOCAL_DOMAIN;
  648.  
  649.     paramPtr = (FsRemoteSetAttrParams *) storagePtr->requestParamPtr;
  650.     attrPtr = ¶mPtr->attrs;
  651.     fileIDPtr = ¶mPtr->fileID;
  652.  
  653.     hdrPtr = VerifyIOHandle(fileIDPtr);
  654.     if (fileIDPtr->type == FSIO_LCL_PFS_STREAM) {
  655.     if (hdrPtr == (Fs_HandleHeader *)NIL) {
  656.         return(FS_STALE_HANDLE);
  657.     }
  658.     domainType = FS_PSEUDO_DOMAIN;
  659.     } else if (hdrPtr == (Fs_HandleHeader *)NIL) {
  660.     status = Fsio_LocalFileHandleInit(fileIDPtr, (char *)NIL,
  661.                 (Fsdm_FileDescriptor *) NIL, FALSE, 
  662.             (Fsio_FileIOHandle **)&hdrPtr);
  663.     if (status != SUCCESS) {
  664.         return(status);
  665.     }
  666.     }
  667.     fs_Stats.srvName.setAttrs++;
  668.     Fsutil_HandleUnlock(hdrPtr);
  669.     status = (*fs_AttrOpTable[domainType].setAttr)(fileIDPtr, attrPtr,
  670.                         ¶mPtr->ids,paramPtr->flags);
  671. #ifdef lint
  672.     status = FslclSetAttr(fileIDPtr, attrPtr, ¶mPtr->ids,paramPtr->flags);
  673.     status = FspdevPseudoSetAttr(fileIDPtr,attrPtr, ¶mPtr->ids,paramPtr->flags);
  674. #endif lint
  675.     Fsutil_HandleRelease(hdrPtr, FALSE);
  676.  
  677.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  678.         (ClientData)NIL);
  679.     return(SUCCESS);
  680. }
  681.  
  682.  
  683. /*
  684.  *----------------------------------------------------------------------
  685.  *
  686.  * Fsrmt_GetIOAttr --
  687.  *
  688.  *    Get the attributes cached at a remote I/O server.  This makes the
  689.  *    RPC_FS_GET_IO_ATTR RPC to the I/O server which then calls
  690.  *    stream-type getIOAttrs routine.
  691.  *
  692.  * Results:
  693.  *    An error code.
  694.  *
  695.  * Side effects:
  696.  *    Update attributes structure with info from the I/O server.
  697.  *
  698.  *----------------------------------------------------------------------
  699.  */
  700. /*ARGSUSED*/
  701. ReturnStatus
  702. Fsrmt_GetIOAttr(fileIDPtr, clientID, attrPtr)
  703.     register Fs_FileID        *fileIDPtr;    /* Remote device/pipe fileID */
  704.     int                clientID;    /* IGNORED, implicitly passed
  705.                          * by the RPC system. */
  706.     register Fs_Attributes    *attrPtr;    /* In/Out - the attributes are
  707.                          * updated by the I/O server */
  708. {
  709.     register ReturnStatus status;
  710.     Rpc_Storage storage;
  711.     Fs_GetAttrResultsParam    getAttrResultsParam;
  712.  
  713.     /*
  714.      * We don't want to do full RPC's to hosts we're pretty sure are down.
  715.      */
  716.     if (Recov_IsHostDown(fileIDPtr->serverID) == FAILURE) {
  717.     printf(
  718.         "Fsrmt_GetIOAttr: skipping device <%d,%d> at server %d: host is down.\n",
  719.         fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  720.     return(SUCCESS);
  721.     }
  722.  
  723.     getAttrResultsParam.attrResults.fileID = *fileIDPtr;
  724.     getAttrResultsParam.attrResults.attrs = *attrPtr;
  725.     /*
  726.      * We have to fix up the fileID of control handles in the case that
  727.      * the pseudo-device server is remote from us.  The problem is that
  728.      * we have to RPC to the pseduo-device server, but the fileID of the
  729.      * control stream (where the access/modify times are) has the
  730.      * file serverID.  Fortuneatly this is in the regular attributes so
  731.      * we can patch it up.  We add two lines of code here instead of
  732.      * nearly duplicating this procedure into a FsRmtControlGetIOAttr
  733.      * routine that has the patch.
  734.      */
  735.     if (fileIDPtr->type == FSIO_RMT_CONTROL_STREAM) {
  736.     getAttrResultsParam.attrResults.fileID.serverID = attrPtr->serverID;
  737.     }
  738.  
  739.     storage.requestParamPtr = (Address) &getAttrResultsParam;
  740.     storage.requestParamSize = sizeof(Fs_GetAttrResultsParam);
  741.     storage.requestDataPtr = (Address) NIL;
  742.     storage.requestDataSize = 0;
  743.  
  744.     storage.replyParamPtr = (Address) attrPtr;
  745.     storage.replyParamSize = sizeof(Fs_Attributes);
  746.     storage.replyDataPtr = (Address) NIL;
  747.     storage.replyDataSize = 0;
  748.  
  749.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_GET_IO_ATTR, &storage);
  750.     /*
  751.      * We punt on I/O server recovery, and mask errors so a stat() works.
  752.      */
  753.     if (status != SUCCESS) {
  754.     printf(
  755.         "Fsrmt_GetIOAttr failed <%x>: device <%d,%d> at server %d\n",
  756.         status, fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  757.     status = SUCCESS;
  758.     }
  759.  
  760.     return(status);
  761. }
  762.  
  763. /*
  764.  *----------------------------------------------------------------------
  765.  *
  766.  * Fsrmt_RpcGetIOAttr --
  767.  *
  768.  *    Service stub for the RPC_FS_GET_IO_ATTR call.  This calls
  769.  *    the stream-type routine to get attributes cached at the I/O server.
  770.  *
  771.  * Results:
  772.  *    If this procedure returns SUCCESS then a reply has been sent to
  773.  *    the client.  If the arguments are bad then an error is 
  774.  *    returned and the main level sends back an error reply.
  775.  *
  776.  * Side effects:
  777.  *    None.
  778.  *
  779.  *----------------------------------------------------------------------
  780.  */
  781. /*ARGSUSED*/
  782. ReturnStatus
  783. Fsrmt_RpcGetIOAttr(srvToken, clientID, command, storagePtr)
  784.     ClientData          srvToken;    /* Handle on server process passed to
  785.                       * Rpc_Reply */
  786.     int          clientID;    /* Sprite ID of client host */
  787.     int          command;    /* IGNORED */
  788.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  789.                      * request buffers and also indicate 
  790.                      * the exact amount of data in the 
  791.                      * request buffers.  The reply fields 
  792.                      * are initialized to NIL for the
  793.                       * pointers and 0 for the lengths.  
  794.                      * This can be passed to Rpc_Reply */
  795. {
  796.     register ReturnStatus    status;
  797.     register Fs_HandleHeader    *hdrPtr;
  798.     register Fs_FileID        *fileIDPtr;
  799.     Fs_Attributes        *attrPtr;
  800.     Fs_GetAttrResultsParam    *getAttrResultsParamPtr;
  801.  
  802.     getAttrResultsParamPtr =
  803.         (Fs_GetAttrResultsParam *) storagePtr->requestParamPtr;
  804.     fileIDPtr = &(getAttrResultsParamPtr->attrResults.fileID);
  805.     attrPtr = &(getAttrResultsParamPtr->attrResults.attrs);
  806.  
  807.     hdrPtr = VerifyIOHandle(fileIDPtr);
  808.     if (hdrPtr != (Fs_HandleHeader *) NIL) {
  809.     /*
  810.      * If someone has the I/O device open we'll have a handle and
  811.      * should go get the access and modify times.
  812.      */
  813.     fs_Stats.srvName.getIOAttrs++;
  814.     Fsutil_HandleUnlock(hdrPtr);
  815.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].getIOAttr)
  816.         (&hdrPtr->fileID, clientID, attrPtr);
  817. #ifdef lint
  818.     status = Fsio_DeviceGetIOAttr(&hdrPtr->fileID, rpc_SpriteID, attrPtr);
  819.     status = Fsio_PipeGetIOAttr(&hdrPtr->fileID, rpc_SpriteID, attrPtr);
  820.     status = FspdevControlGetIOAttr(&hdrPtr->fileID, rpc_SpriteID,attrPtr);
  821. #endif lint
  822.     Fsutil_HandleRelease(hdrPtr, FALSE);
  823.     } else {
  824.     /*
  825.      * No information to add. We just return what was passed to us.
  826.      */
  827.     status = SUCCESS;
  828.     }
  829.     if (status == SUCCESS) {
  830.     storagePtr->replyParamPtr = (Address) attrPtr;
  831.     storagePtr->replyParamSize = sizeof(Fs_Attributes);
  832.     }
  833.     /*
  834.      * No clean-up call-back needed because we are returning the attributes
  835.      * that are sitting in the request buffer.
  836.      */
  837.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  838.     return(SUCCESS);
  839. }
  840.  
  841. /*
  842.  *----------------------------------------------------------------------
  843.  *
  844.  * Fsrmt_SetIOAttr --
  845.  *
  846.  *    Set the attributes cached at a remote I/O server.  This makes the
  847.  *    RPC_FS_SET_IO_ATTR RPC to the I/O server which then calls
  848.  *    stream-type setIOAttrs routine.
  849.  *
  850.  * Results:
  851.  *    An error code.
  852.  *
  853.  * Side effects:
  854.  *    Set attributes cached with the I/O server.
  855.  *
  856.  *----------------------------------------------------------------------
  857.  */
  858. /*ARGSUSED*/
  859. ReturnStatus
  860. Fsrmt_SetIOAttr(fileIDPtr, attrPtr, flags)
  861.     register Fs_FileID        *fileIDPtr;    /* Remote device/pipe fileID */
  862.     register Fs_Attributes    *attrPtr;    /* Attributes to copy */
  863.     int                flags;        /* What attributes to set */
  864. {
  865.     register ReturnStatus    status;
  866.     Rpc_Storage            storage;
  867.     FsRemoteSetAttrParams    setAttrParam;
  868.  
  869.     setAttrParam.fileID = *fileIDPtr;
  870.     setAttrParam.attrs = *attrPtr;
  871.     setAttrParam.flags = flags;
  872.     /*
  873.      * We have to fix up the fileID of control handles in the case that
  874.      * the pseudo-device server is remote from us.  The problem is that
  875.      * we have to RPC to the pseduo-device server, but the fileID of the
  876.      * control stream (where the access/modify times are) has the
  877.      * file serverID.  Fortuneatly this is in the regular attributes so
  878.      * we can patch it up.  We add two lines of code here instead of
  879.      * nearly duplicating this procedure into a FsRmtControlSetIOAttr
  880.      * routine that has the patch.
  881.      */
  882.     if (fileIDPtr->type == FSIO_RMT_CONTROL_STREAM) {
  883.     setAttrParam.fileID.serverID = attrPtr->serverID;
  884.     }
  885.     storage.requestParamPtr = (Address) &setAttrParam;
  886.     storage.requestParamSize = sizeof(FsRemoteSetAttrParams);
  887.     storage.requestDataPtr = (Address) NIL;
  888.     storage.requestDataSize = 0;
  889.  
  890.     storage.replyParamPtr = (Address) NIL;
  891.     storage.replyParamSize = 0;
  892.     storage.replyDataPtr = (Address) NIL;
  893.     storage.replyDataSize = 0;
  894.  
  895.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_SET_IO_ATTR, &storage);
  896.     /*
  897.      * We punt on I/O server recovery, and mask errors so a chmod() works.
  898.      */
  899.     if (status != SUCCESS) {
  900.     printf(
  901.         "Fsrmt_SetIOAttr failed <%x>: device <%d,%d> at server %d\n",
  902.         status, fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  903.     status = SUCCESS;
  904.     }
  905.     return(status);
  906. }
  907.  
  908. /*
  909.  *----------------------------------------------------------------------
  910.  *
  911.  * Fsrmt_RpcSetIOAttr --
  912.  *
  913.  *    Service stub for the RPC_FS_SET_IO_ATTR call.  This calls
  914.  *    the stream-type routine to set attributes cached at the I/O server.
  915.  *
  916.  * Results:
  917.  *    If this procedure returns SUCCESS then a reply has been sent to
  918.  *    the client.  If the arguments are bad then an error is 
  919.  *    returned and the main level sends back an error reply.
  920.  *
  921.  * Side effects:
  922.  *    None.
  923.  *
  924.  *----------------------------------------------------------------------
  925.  */
  926. /*ARGSUSED*/
  927. ReturnStatus
  928. Fsrmt_RpcSetIOAttr(srvToken, clientID, command, storagePtr)
  929.     ClientData          srvToken;    /* Handle on server process passed to
  930.                       * Rpc_Reply */
  931.     int          clientID;    /* Sprite ID of client host */
  932.     int          command;    /* IGNORED */
  933.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  934.                      * request buffers and also indicate 
  935.                      * the exact amount of data in the 
  936.                      * request buffers.  The reply fields 
  937.                      * are initialized to NIL for the
  938.                       * pointers and 0 for the lengths.  
  939.                      * This can be passed to Rpc_Reply */
  940. {
  941.     register ReturnStatus    status;
  942.     register Fs_HandleHeader    *hdrPtr;
  943.     register Fs_FileID        *fileIDPtr;
  944.     Fs_Attributes        *attrPtr;
  945.     FsRemoteSetAttrParams    *setAttrParamPtr;
  946.  
  947.     setAttrParamPtr =
  948.         (FsRemoteSetAttrParams *) storagePtr->requestParamPtr;
  949.     fileIDPtr = &(setAttrParamPtr->fileID);
  950.     attrPtr = &(setAttrParamPtr->attrs);
  951.  
  952.    fs_Stats.srvName.setIOAttrs++;
  953.    hdrPtr = VerifyIOHandle(fileIDPtr);
  954.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  955.     /*
  956.      * Noone has the I/O device open so we don't have a handle.
  957.      * Return SUCCESS but take no action.
  958.      */
  959.     return(SUCCESS);
  960.     } 
  961.     Fsutil_HandleUnlock(hdrPtr);
  962.  
  963.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].setIOAttr)
  964.         (&hdrPtr->fileID, attrPtr, setAttrParamPtr->flags);
  965. #ifdef lint
  966.     status = Fsio_DeviceSetIOAttr(&hdrPtr->fileID, attrPtr,setAttrParamPtr->flags);
  967.     status = Fsio_PipeSetIOAttr(&hdrPtr->fileID, attrPtr, setAttrParamPtr->flags);
  968.     status = FspdevControlSetIOAttr(&hdrPtr->fileID, attrPtr,
  969.                     setAttrParamPtr->flags);
  970. #endif lint
  971.  
  972.     Fsutil_HandleRelease(hdrPtr, FALSE);
  973.  
  974.     /*
  975.      * No clean-up call-back needed because there are no reply parameters.
  976.      */
  977.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  978.     return(SUCCESS);
  979. }
  980.  
  981. /*
  982.  *----------------------------------------------------------------------
  983.  *
  984.  * VerifyIOHandle --
  985.  *
  986.  *    Verify an I/O handle from a remote client.  This is only used when
  987.  *    getting/setting attributes.  We do not require that the client be
  988.  *    listed for the I/O handle because in two important cases it won't be.
  989.  *    The first is if we are the I/O server for a device, and someone
  990.  *    does a Fs_GetAttributes(pathname, ...).  We are contacted for the
  991.  *    latest I/O attributes, and the client won't have opened the device.
  992.  *    The second case is if we are the name server and someone is doing
  993.  *    a Fs_GetAttributesID(streamID, ...).  Here the I/O server has the
  994.  *    client in its list, but we (the name server) do not.
  995.  *
  996.  * Results:
  997.  *    A locked pointer to the I/O handle if it exists.
  998.  *
  999.  * Side effects:
  1000.  *    The returned handle must be released because we fetch it here.
  1001.  *
  1002.  *----------------------------------------------------------------------
  1003.  */
  1004. static Fs_HandleHeader *
  1005. VerifyIOHandle(fileIDPtr)
  1006.     Fs_FileID *fileIDPtr;
  1007. {
  1008.     if (fileIDPtr->type <= 0 || fileIDPtr->type >= FSIO_NUM_STREAM_TYPES) {
  1009.     printf(
  1010.         "Bad stream type (%d) in VerifyIOHandle.\n",
  1011.         fileIDPtr->type);
  1012.     return((Fs_HandleHeader *)NIL);
  1013.     } else {
  1014.     fileIDPtr->type = fsio_RmtToLclType[fileIDPtr->type];
  1015.     }
  1016.     return(Fsutil_HandleFetch(fileIDPtr));
  1017. }
  1018.